{
	"title": "SearXNG instances",
	"description": "Unofficial schema draft for /data/instances.json from the searx-space project, see https://github.com/searxng/searx-space or https://searx.space",
	"$defs": {
		"ip_metadata": {
			"description": "IP-address metadata",
			"type": "object",
			"properties": {
				"reverse": {
					"oneOf": [
						{
							"type": "string"
						},
						{
							"type": "null"
						}
					]
				},
				"field_type": {
					"description": "DNS record type",
					"type": "string",
					"minLength": 1,
					"maxLength": 10
				},
				"asn_cidr": {
					"description": "IPv4 or IPv6 netmask",
					"type": "string",
					"minLength": 3,
					"maxLength": 44
				}
			}
		},

		"ipaddress": {
			"description": "IPv4 or IPv6 address",
			"anyOf": [
				{
					"type": "string",
					"description": "IPv4 address",
					"format": "ipv4"
				},
				{
					"type": "string",
					"description": "IPv6 address",
					"format": "ipv6"
				}
			]
			
		},

		"netmask": {
			"description": "IPv4 or IPv6 netmask",
			"oneOf": [
				{
					"description": "IPv4 netmask",
					"type": "string",
					"pattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/[0-9]{1,2}$"
				},
				{
					"description": "IPv6 netmask",
					"type": "string",
					"pattern": "^(([A-Fa-f0-9]{1,4}:){1,8}):/([0-9]|[1-9][0-9]|1[01][0-9]|12[0-8])$"
				}
			]
		},

		"ips": {
			"type": "object",
			"propertyNames": {
				"$ref": "#/$defs/ipaddress"
			},
			"additionalProperties": {
				"$ref": "#/$defs/ip_metadata"
			}
		},

		"ipv6": {
			"description": "IPv6 support",
			"oneOf": [
				{"type": "boolean"},
				{"type": "null"}
			]
		},

		"grade": {
			"oneOf": [
				{
					"type": "string",
					"pattern": "([A-F]|\\?)(\\+)?"
				},
				{
					"type": "boolean"
				},
				{
					"type": "null"
				}
			]
		},
		"gradeUrl": {
			"type": "string",
			"format": "uri"
		},

		"timingItem": {
			"type": "object",
			"properties": {
				"median": {"type": "number"},
				"stdev": {"type": "number"},
				"value": {"type": "number"},
				"mean": {"type": "number"}
			}
		},

		"timings": {
			"type": "object",
			"properties": {
				"success_percentage": {
					"type": "number"
				},
				"all": {"$ref": "#/$defs/timingItem"},
				"server": {"$ref": "#/$defs/timingItem"},
				"load": {"$ref": "#/$defs/timingItem"},
				"error": {"type": "string"}
			}
		},

		"ressourcesItem": {
			"type": "object",
			"propertyNames": {
				"format": "uri"
			},
			"additionalProperties": {
				"type": "object",
				"properties": {
					"hashRef": {
						"type": "number",
						"minimum": 0,
						"maximum": 100
					}
				}
			}
		},

		"uptimeItem": {
			"type": "number",
			"minimum": 0,
			"maximum": 100
		},

		"statsItem": {
			"anyOf": [
				{
					"type": "number",
					"minimum": 0.0,
					"maximum": 100.0
				},
				{"type": "null"}
			]
		}
	},
	"type": "object",
	"properties": {
		"metadata": {
			"type": "object",
			"properties": {
				"timestamp": {"type": "number"},
				"ips": {"$ref": "#/$defs/ips"},
				"ipv6": {"$ref": "#/$defs/ipv6"}
			}
		},
		"instances": {
			"type": "object",
			"description": "Object holding data of SearXNG instances",
			"propertyNames": {
				"format": "uri"
			},
			"additionalProperties": {
				"type": "object",
				"properties": {
					"analytics": {"type": "boolean"},
					"comments": {
						"type": "array",
						"items": {
							"type": "string"
						}
					},
					"alternativeUrls": {
						"description": "Alternative URLs",
						"type": "object",
						"propertyNames": {
							"type": "string",
							"description": "Alternative URL",
							"format": "uri"
						},
						"additionalProperties": {
							"type": "string",
							"description": "Comment",
							"maxLength": 1024
						}
					},
					"docs_url": {
						"oneOf": [
							{"type": "string", "format": "uri"},
							{"type": "null"}
						]
					},
					"generator": {
						"oneOf": [
							{"type": "string"},
							{"type": "null"}
						]
					},
					"git_url": {
						"oneOf": [
							{
								"type": "string",
								"format": "uri"
							},
							{
								"type": "null"
							}
						]
					},
					"http": {
						"type": "object",
						"properties": {
							"error": {
								"oneOf": [
									{"type": "string"},
									{"type": "null"}
								]
							},
							"status_code": {
								"oneOf": [
									{
										"type": "number",
										"minimum": 0,
										"maximum": 530
									},
									{
										"type": "null"
									}
								]
							},
							"grade": {
								"$ref": "#/$defs/grade"
							},
							"gradeUrl": {
								"$ref": "#/$defs/gradeUrl"
							}
						}
					},
					"contact_url": {
						"oneOf": [
							{"type": "string"},
							{"type": "boolean"},
							{"type": "null"}
						]
					},
					"main": {"type": "boolean"},
					"network_type": {
						"oneOf": [
							{
								"type": "string",
								"enum": [
									"normal",
									"tor"
								]
							},
							{"type": "null"}
						]
					},
					"timing": {
						"type": "object",
						"properties": {
							"initial": {"$ref": "#/$defs/timings"},
							"search": {"$ref": "#/$defs/timings"},
							"search_wp": {"$ref": "#/$defs/timings"},
							"search_go": {"$ref": "#/$defs/timings"}
						}
					},
					"tls": {
						"type": "object",
						"properties": {
							"certificate": {
								"type": "object",
								"properties": {
									"OCSP": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uri"
										}
									},
									"caIssuers": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uri"
										}
									},
									"crlDistributionPoints": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uri"
										}
									},
									"issuer": {
										"type": "object",
										"properties": {
											"commonName": {
												"type": "string"
											},
											"countryName": {
												"type": "string"
											},
											"organizationName": {
												"type": "string"
											}
										}
									},
									"subject": {
										"type": "object",
										"properties": {
											"commonName": {
												"oneOf": [
													{"type": "string"},
													{"type": "null"}
												]
											},
											"countryName": {
												"oneOf": [
													{"type": "string"},
													{"type": "null"}
												]
											},
											"organizationName": {
												"oneOf": [
													{"type": "string"},
													{"type": "null"}
												]
											},
											"altName": {
												"type": "string"
											}
										}
									},
									"notAfter": {
										"type": "string",
										"pattern": "^[0-9]+?Z$"
									},
									"notBefore": {
										"type": "string",
										"pattern": "^[0-9]+?Z$"
									},
									"serialNumber": {
										"type": "string",
										"pattern": "^[0-9A-F]{22,36}$"
									},
									"sha256": {
										"type": "string",
										"pattern": "^([0-9A-F]{2}:){31}[0-9A-F]{2}$"
									},
									"signatureAlgorithm": {
										"type": "string",
										"enum": [
											"sha256WithRSAEncryption",
											"sha384WithRSAEncryption",
											"ecdsa-with-SHA384"
										]
									},
									"version": {
										"type": "number",
										"enum": [1, 2, 3]
									}
								},
								"additionalProperties": false
							},
							"version": {
								"type": "string",
								"enum": ["TLSv1.2", "TLSv1.3"]
							},
							"grade": {
								"$ref": "#/$defs/grade"
							},
							"gradeUrl": {
								"$ref": "#/$defs/gradeUrl"
							}
						},
						"additionalProperties": false
					},
					"version": {
						"oneOf": [
							{
								"description": "Semantic major.minor.patch version plus additions, or Date version year.month.day version plus additions",
								"type": "string",
								"pattern": "^([0-9]{1,4}\\.){2}([0-9]{1,4})(\\+[a-fA-F0-9]{1,9})?(\\+dirty)?( \\([a-fA-F0-9]{1,9}\\))?$"
							},
							{
								"description": "Semantic versions with - as extras seperator",
								"type": "string",
								"pattern": "^([0-9]{1,3}\\.){2}([0-9]{1,3})(-[0-9]{1,3})(-[a-fA-F0-9]{1,9})$"
							},
							{
								"type": "null"
							}
						]
					},
					"html": {
						"description": "TODO",
						"type": "object",
						"additionalProperties": false,
						"properties": {
							"grade": {
								"description": "TODO look at https://searx.space/ (V=Vanilla, C=Custom, F=Fork, Cjs=Custom and custom JS)",
								"type": "string",
								"pattern": "^(A|B|C|D|E|F|V|\\?)?(js|js\\?)?(, \\?)?$"
							},
							"ressources": {
								"type": "object",
								"additionalProperties": false,
								"properties": {
									"css": {"$ref": "#/$defs/ressourcesItem"},
									"img": {"$ref": "#/$defs/ressourcesItem"},
									"link": {"$ref": "#/$defs/ressourcesItem"},
									"script": {"$ref": "#/$defs/ressourcesItem"},
									"other": {"$ref": "#/$defs/ressourcesItem"},
									"inline_script": {
										"description": "TODO Unknown",
										"type": "array",
										"items": {"type": "string"}
									},
									"inline_style": {
										"description": "TODO Unknown",
										"type": "array",
										"items": {"type": "string"}
									},
									"error": {
										"description": "TODO",
										"type": "string"
									}
								}
							}
						}
					},
					"engines": {
						"description": "TODO",
						"type": "object",
						"propertyNames": {
							"type": "string",
							"minLength": 1,
							"maxLength": 128
						},
						"additionalProperties": {
							"type": "object",
							"properties": {
								"error_rate": {
									"oneOf": [
										{
											"type": "number",
											"minimum": 0,
											"maximum": 100
										},
										{
											"type": "null"
										}
									]
								},
								"errors": {
									"type": "array",
									"items": {
										"type": "number",
										"minimum": 0,
										"maximum": 100
									}
								},
								"checker": {
									"type": "object",
									"description": "TODO"
								}
							},
							"additionalProperties": false
						}
					},
					"uptime": {
						"oneOf": [
							{
								"description": "TODO",
								"type": "object",
								"properties": {
									"uptimeDay": {"$ref": "#/$defs/uptimeItem"},
									"uptimeWeek": {"$ref": "#/$defs/uptimeItem"},
									"uptimeMonth": {"$ref": "#/$defs/uptimeItem"},
									"uptimeYear": {"$ref": "#/$defs/uptimeItem"}
								},
								"additionalProperties": false
							},
							{"type": "null"}
						]
					},
					"error": {
						"type": "string"
					},
					"network": {
						"description": "TODO",
						"type": "object",
						"properties": {
							"ips": {"$ref": "#/$defs/ips"},
							"ipv6": {"$ref": "#/$defs/ipv6"},
							"asn_privacy": {
								"type": "number",
								"enum": [0, 1]
							},
							"dnssec": {
								"type": "number",
								"enum": [1, 2]
							}
						},
						"additionalProperties": false
					}
				},
				"required": ["analytics", "alternativeUrls", "comments", "git_url", "http", "network_type"],
				"additionalProperties": false
			},
			"minProperties": 1,
			"maxProperties": 4096
		},

		"engines": {
			"type": "object",
			"propertyNames": {
				"type": "string",
				"minLength": 1,
				"maxLength": 255
			},
			"additionalProperties": {
				"type": "object",
				"additionalProperties": false,
				"properties": {
					"categories": {
						"type": "array",
						"items": {
							"type": "string",
							"minLength": 1,
							"maxLength": 255
						}
					},
					"language_support": {"type": "boolean"},
					"paging": {"type": "boolean"},
					"safesearch": {"type": "boolean"},
					"time_range_support": {"type": "boolean"},
					"shortcut": {"type": "string", "minLength": 1, "maxLength": 32},
					"stats": {
						"type": "object",
						"properties": {
							"error_rate": {"$ref": "#/$defs/statsItem"},
							"instance_count": {"$ref": "#/$defs/statsItem"},
							"stats_count": {"$ref": "#/$defs/statsItem"}
						}
					}
				}
			}
		},

		"engine_errors": {
			"type": "array",
			"items": {
				"type": "string",
				"minLength": 1,
				"maxLength": 255
			}
		},

		"categories": {
			"type": "array",
			"items": {
				"type": "string",
				"minLength": 1,
				"maxLength": 255
			}
		},

		"hashes": {
			"type": "array",
			"items": {
				"type": "object",
				"additionalProperties": false,
				"properties": {
					"count": {"type": "number"},
					"hash": {
						"type": "string",
						"minLength": 1,
						"maxLength": 255
					},
					"forks": {
						"type": "array",
						"items": {
							"type": "number",
							"minimum": 0,
							"maximum": 255
						}
					},
					"unknown": {"type": "boolean"}
				}
			}
		},

		"cidrs": {
			"type": "object",
			"propertyNames": {
				"$ref": "#/$defs/netmask"
			},
			"additionalProperties": {
				"type": "object",
				"properties": {
					"asn": {"type": "string"},
					"asn_country_code": {"type": "string"},
					"asn_description": {"type": "string"},
					"asn_privacy": {"type": "number"},
					"network_country": {"type": "string"}
				}
			}
		},

		"forks": {
			"type": "array",
			"items": {
				"type": "string",
				"format": "uri"
			}
		}
	}
}
